package com.test.strategy;

import com.test.definition.BeanDefinition;
import com.test.exception.BeansException;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.NoOp;

import java.lang.reflect.Constructor;

/**
 * 使用CGLIB实现的子类实例化策略
 * 这个类实现了InstantiationStrategy接口，通过覆盖instantiate方法使用CGLIB来创建bean的实例
 */
public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy{
    /**
     * 实例化bean的方法
     *
     * @param beanDefinition Bean的定义信息，包含Bean类、作用域等
     * @param beanName Bean的名称
     * @param ctor 构造函数，可能为null，用于实例化Bean
     * @param args 构造函数的参数，可能为null
     * @return 返回实例化的Bean对象
     * @throws BeansException 如果实例化Bean失败，则抛出此异常
     */
    @Override
    public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor<?> ctor, Object[] args) {
        try{
            // 创建CGLIB的Enhancer对象，用于生成子类
            Enhancer enhancer = new Enhancer();
            // 设置父类为BeanDefinition中定义的类
            enhancer.setSuperclass(beanDefinition.getBeanClass());
            // 设置回调方法为空操作，因为不需要额外的代理逻辑
            enhancer.setCallback(NoOp.INSTANCE);
            // 如果没有指定构造函数，直接创建子类实例
            if (null == ctor) {
                return enhancer.create();
            }
            // 如果参数为空，初始化参数数组
            if (args == null){
                args = new Object[0];
            }
            // 检查参数个数是否匹配，如果不匹配抛出异常
            if (args.length != ctor.getParameterCount()){
                throw new RuntimeException("构造函数参数个数不匹配： " + beanName +
                        ", 期望" + ctor.getParameterCount() + "个， 实际" + args.length);
            }
            // 使用指定的构造函数和参数创建子类实例
            return enhancer.create(ctor.getParameterTypes(), args);
        }catch (Exception e){
            // 如果实例化失败，抛出BeansException异常
            throw new BeansException("使用CGLIB实例化bean失败 [" + beanName + "]", e);
        }
    }
}
